package com.google.wavesurferrobot.textmining;

/*
*************************************************************************************************
* File:         InfoGain.java                                                                   *
* Usage:        InfoGain impelements the IG measure                                             *
*************************************************************************************************
* IDE/Compiler: For the development needs we used NetBeans 5.0 and JRE 1.5.0_06 on WinXP Home   *
*************************************************************************************************
* License:      (LGPL) GNU Lesser General Public License                                        *
*               http://www.opensource.org/licenses/lgpl-license.php                             *
*************************************************************************************************
*         Originally written by George Tsatsaros (gbt@aueb.gr)                                  *      
*               Author         :  Panayiotis Papadopoulos (3010010)                             *
*               Website        :  http://dias.aueb.gr/~p3010010/                                *
*               E-mail         :  papado@freemail.gr                                            *
*                                 p3010010@dias.aueb.gr                                         *
*               MSN messenger  :  pap5@hotmail.com                                              *
*               Skype          :  papOnSlayer                                                   *
*                                                                                               *
* Contact:  Feel free to contact with me for any question/suggestion using the email(s) above   *
*************************************************************************************************
*/

import java.util.Hashtable;
import java.util.Enumeration;
import java.lang.Math.*;

public class InfoGain
{
    private String token;
    private double probToken;
    private double comProbToken;

    private double ig;

    public InfoGain(String token, double entropy, Hashtable category)
    {
        this.token = token;
        computeInfoGain(entropy, category);
    }

    public double getInfoGain()
    {
        return ig;
    }

    //IG(t) = - entropy + Pr(t) * Sum(Pr(Ci|t) * lg(Pr(Ci|t))) + Pr(t') * Sum(Pr(Ci|t') * lg(Pr(Ci|t')))
    private void computeInfoGain(double entropy, Hashtable category)
    {
        double sum = 0;
        double comSum = 0;

        computeProbToken(category);

        for (Enumeration e = category.elements(); e.hasMoreElements(); )
        {
            Category catObj = (Category) e.nextElement();

            double probTokenBelongToCategory = getProbTokenBelongToCategory(catObj);
            sum += probTokenBelongToCategory * lg(probTokenBelongToCategory);

            double comProbTokenBelongToCategory = getComProbTokenBelongToCategory(catObj);
            comSum += comProbTokenBelongToCategory * lg(comProbTokenBelongToCategory);
        }

        ig = - entropy + (probToken * sum) + (comProbToken * comSum);
    }

    //Pr(t) = Number of t occurences / total number of all tokens
    //Pr(t') = 1 - Pr(t)
    private void computeProbToken(Hashtable category)
    {
        int sumT = 0;
        int sumAll = 0;

        for (Enumeration e = category.elements(); e.hasMoreElements(); )
        {
            Category catObj = (Category) e.nextElement();

            //total occurences of the token in all categories
            sumT += catObj.getTokenOccurences(token);

            //total number of tokens' occurences
            sumAll += catObj.getCategoryTokensNum();
        }

        probToken = (double) sumT / (double) sumAll;
        comProbToken = (double) 1 - probToken;
    }


    //Pr(t|Ci) = Number of t occurences in the category / total number of all tokens
    //Pr(t'|Ci) = 1 - Pr(t|Ci)
    private double getProbTokenOccurInCategory(Category catObj)
    {
        return (double) catObj.getTokenOccurences(token) / (double) catObj.getCategoryTokensNum();
    }


    //Pr(Ci|t) = ( Pr(t|Ci) * Pr(Ci) ) / Pr(t)
    private double getProbTokenBelongToCategory(Category catObj)
    {
        double probTokenOccurInCategory = getProbTokenOccurInCategory(catObj);

        double probTokenBelongToCategory = probTokenOccurInCategory * catObj.getCategoryProbability() / probToken;
        return probTokenBelongToCategory;
    }

    //Pr(Ci|t') = ( ( 1 - Pr(t|Ci) ) * Pr(Ci) ) / ( 1 - Pr(t) )
    private double getComProbTokenBelongToCategory(Category catObj)
    {
        double comProbTokenOccurInCategory = 1 - getProbTokenOccurInCategory(catObj);

        double comProbTokenBelongToCategory = (comProbTokenOccurInCategory * catObj.getCategoryProbability()) / comProbToken;
        return comProbTokenBelongToCategory;
    }


    private double lg(double x)
    {
        //java.lang.Math log(double) returns the natural logarithm
        if (x==0)
            return 0;
        else
            return (Math.log(x) / Math.log(2));
    }


}//Class InfoGain.
